﻿using CommonLibrary.Models;
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Web;
using BLToolkit.Data;
using BLToolkit.Data.Linq;
using System.Security.Cryptography;
using CommonHelper;

namespace CommonLibrary
{
    public static class UserAction
    {
        public class UserToken
        {
            public int UserId { get; set; }
            public string LoginName { get; set; }
            public string UserName { get; set; }
            public string WorkEmail { get; set; }

            public bool IsSupperAdmin { get; set; }
            public bool IsAdmin { get; set; }
        }

        private static ConcurrentDictionary<UserToken, bool> _caches =
            new ConcurrentDictionary<UserToken, bool>();

        public static UserToken GetCurrentUser()
        {
            if (HttpContext.Current == null) return null;
            var user = HttpContext.Current.Session["Current_User"] as UserToken;
            return user;
        }

        public static string GetIPAddress()
        {
            if (HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)
            {
                return HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            }
            else
            {
                return HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            }
        }

        public static bool CheckValue(string value)
        {
            if (value == null || value.Length == 0) return false;
            for (int i = 0; i < value.Length; i++)
            {
                if (!((value[i] >= 'a' && value[i] <= 'z') ||
                      (value[i] >= 'A' && value[i] <= 'Z') ||
                      (value[i] >= '0' && value[i] <= '9') ||
                      (value[i] == '_')))
                    return false;
            }

            return true;
        }        

        public static void Logout()
        {
            var token = GetCurrentUser();
            bool result;
            if (token != null)
                _caches.TryRemove(token, out result);
            if(HttpContext.Current != null)
                HttpContext.Current.Session.RemoveAll();        
        }

        public static bool Login(string loginName, string password)
        {
            using (CommonDatabase db = new CommonDatabase(CommonOption.ReadWrite))
            {
                db.BeginTransaction();
                string sessionId = HttpContext.Current.Session.SessionID;

                var query = from u in db.sys_User
                            where u.LoginName == loginName &&
                                  u.State == 1
                            select u;

                var user = query.FirstOrDefault();
                if (user == null) return false;                
                if (!CheckPassword(user, password)) return false;

                db.sys_User.Where(k => k.Id == user.Id)
                  .Set(k => k.LastLoginTime, Sql.GetDate())
                  .Set(k => k.LastIPAddress, GetIPAddress())
                  .Update();

                db.CommitTransaction();

                var info = db.sys_UserInfo.Where(k => k.UserId == user.Id).First();
                var token = new UserToken()
                {
                    UserId = user.Id,
                    LoginName = loginName,
                    UserName = info.UserName,
                    WorkEmail = info.WorkEmail,
                    IsSupperAdmin = user.Id == 1,
                    IsAdmin = db.sys_UserRole.Where(k => k.UserId == user.Id && k.RoleId == 2).Count() > 0
                };

                _caches[token] = true;
                HttpContext.Current.Session["current_user"] = token;

                return true;
            }
        }
        
        public static bool CheckPassword(sys_User user, string password)
        {
            var md5 = MD5.Create();
            var encrypt = md5.ComputeHash(Encoding.UTF8.GetBytes(user.LoginName + password + user.Salt))
                             .ToHexString();
            return encrypt == user.Password;
        }

        public static void EncryptPassword(
            string loginName,
            string password, out string encrypt, out string salt)
        {
            var md5 = MD5.Create();
            salt = "abcdefghigklmnopqrstuvwxyz0123456789!@#$%^&*()".GenerateRandomString(6);
            var buffer = md5.ComputeHash(Encoding.UTF8.GetBytes(loginName + password + salt));
            encrypt = buffer.ToHexString();
        }
    }
}